package nc.impl.hrppl.performance.performance;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import nc.bs.framework.common.NCLocator;
import nc.impl.hrppl.HrpplServiceSupport;
import nc.itf.hrpbctp.busictrltype.busictrltype.IBusictrlTypeVOService;
import nc.itf.hrpom.prosetuptask.prosetuptaskvo.IProSetupTaskVOService;
import nc.itf.hrppl.jxaims.jxaimsvo.IJXaimsVOService;
import nc.itf.hrppl.jxaimstype.jxaimstype.IJXaimsTypeVOService;
import nc.itf.hrppl.pjapplication.pjappl.IPJApplHVOService;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.vo.hrpbctp.busctrltype.BusictrlTypeVO;
import nc.vo.hrpbctp.busictrl.BusiCtrlDataVO;
import nc.vo.hrpbctp.busictrl.BusiCtrlDetailVO;
import nc.vo.hrpom.prosetuptask.AggProSetupTaskVO;
import nc.vo.hrpom.prosetuptask.ProSetupTaskVO;
import nc.vo.hrppl.jxaims.JXaimsVO;
import nc.vo.hrppl.pjapplication.AggPjapplVO;
import nc.vo.hrppl.pjapplication.PJApplHVO;
import nc.vo.hrppl.pjapplication.PjapplBVO;
import nc.vo.hrppl.pjapplication.PjapplCVO;
import nc.vo.hrppl.type.JXaimsTypeVO;
import nc.vo.pmpub.project.ProjectHeadVO;
import nc.vo.pub.*;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nccloud.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.itf.hrppl.performance.performance.IPerformanceService;
import nc.jdbc.framework.processor.MapProcessor;
import nc.pub.billcode.vo.BillCodeContext;
import nc.vo.hrppl.component.AggPerformance;
import nc.vo.hrppl.component.Perapplybody;
import nc.vo.hrppl.component.Performance;
import nc.vo.hrppl.component.Properbody;
import nc.vo.pm.util.UFDoubleUtils;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pub.pf.BillStatusEnum;
import nc.vo.pubapp.pattern.pub.SqlBuilder;

public class PerformanceServiceImpl extends HrpplServiceSupport implements IPerformanceService {

	@Override
	public AggPerformance[] listAggPerformanceByPk(String... pks) throws BusinessException {
		return listAggPerformanceByPk(false, pks);
	}

	@Override
	public AggPerformance[] listAggPerformanceByPk(boolean blazyLoad, String... pks) throws BusinessException {
		return dao.listByPksWithOrder(AggPerformance.class, pks, blazyLoad);
	}

	@Override
	public AggPerformance findAggPerformanceByPk(String pk) throws BusinessException {
		return dao.findByPk(AggPerformance.class, pk, false);
	}

	@Override
	public AggPerformance[] listAggPerformanceByCondition(String condition) throws BusinessException {
		return listAggPerformanceByCondition(condition, new String[] { "pk_performance" });
	}

	@Override
	public AggPerformance[] listAggPerformanceByCondition(String condition, String[] orderPath)
			throws BusinessException {
		return dao.listByCondition(AggPerformance.class, condition, false, false, orderPath);
	}

	@Override
	public Performance[] listPerformanceByPk(String... pks) throws BusinessException {
		return dao.listByPk(Performance.class, pks, true);
	}

	@Override
	public Performance findPerformanceByPk(String pk) throws BusinessException {
		return dao.findByPk(Performance.class, pk, true);
	}

	@Override
	public Performance[] listPerformanceByCondition(String condition) throws BusinessException {
		return listPerformanceByCondition(condition, new String[] { "pk_performance" });
	}

	@Override
	public Performance[] listPerformanceByCondition(String condition, String[] orderPath) throws BusinessException {
		return dao.listByCondition(Performance.class, condition, false, false, orderPath);
	}

	@Override
	public String[] listPerformancePkByCond(String condition) throws BusinessException {
		return listPerformancePkByCond(condition, new String[] { "dbilldate desc" });
	}

	@Override
	public String[] listPerformancePkByCond(String condition, String[] orderPath) throws BusinessException {
		if (StringUtils.isEmpty(condition)) {
			condition = " 1 = 1 ";
		}
		StringBuilder sql = new StringBuilder();
		sql.append(" select pk_performance from ").append(Performance.getDefaultTableName());
		sql.append(" where ").append(condition);
		if (ArrayUtils.isNotEmpty(orderPath)) {
			sql.append(" order by ").append(StringUtils.join(orderPath, ", "));
		}
		return (String[]) dao.getBaseDAO().executeQuery(sql.toString(), (rs) -> {
			List<String> pks = new ArrayList<>();
			while (rs.next()) {
				pks.add(rs.getString(1));
			}
			return pks.toArray(new String[0]);
		});
	}

	@Override
	public void initDefaultData(Performance vo) {
		if (vo.getAttributeValue("pk_group") == null) {
			vo.setAttributeValue("pk_group", InvocationInfoProxy.getInstance().getGroupId());
		}
		if (vo.getAttributeValue("billmaker") == null) {
			vo.setAttributeValue("billmaker", InvocationInfoProxy.getInstance().getUserId());
		}
		if (vo.getAttributeValue("maketime") == null) {
			vo.setAttributeValue("maketime", new UFDateTime(InvocationInfoProxy.getInstance().getBizDateTime()));
		}
		if (vo.getAttributeValue("billtype") == null) {
			vo.setAttributeValue("billtype", "JXPJ");
		}
		if (vo.getAttributeValue("approvestatus") == null) {
			vo.setAttributeValue("approvestatus", BillStatusEnum.FREE.toIntValue());
		}
		UFDate newStartingdate = new UFDate(InvocationInfoProxy.getInstance().getBizDateTime());
		if (vo.getAttributeValue("dbilldate") == null) {
			vo.setAttributeValue("dbilldate", newStartingdate);
		}
		vo.setPk_current("1002Z0100000000001K1");
		SqlBuilder querySql = new SqlBuilder();
		querySql.append(
				" select  billtype.PK_BILLTYPECODE transtypecode,billtype.PK_BILLTYPEID transtypepk,billtype.billtypename billtypename ");
		querySql.append(" from bd_billtype billtype ");
		querySql.append(" where pk_billtypecode", "JXPJ-Cxx-01");
		try {
			Map<String, String> transtypeCode = (Map<String, String>) getDao().executeQuery(querySql.toString(),
					new MapProcessor());
			vo.setAttributeValue("transtypepk", transtypeCode.get("transtypepk"));
			vo.setAttributeValue("transtype", "JXPJ-Cxx-01");
		} catch (DAOException e) {
			ExceptionUtils.wrappBusinessException(e.getMessage(), e);
		}

	}

	private BaseDAO basedao;

	private BaseDAO getDao() {
		if (this.basedao == null) {
			return new BaseDAO();
		}
		return this.basedao;
	}

	@Override
	public AggPerformance preAddAggPerformance(AggPerformance vo, Map<String, Object> userJson)
			throws BusinessException {

		getMainVO(vo).setStatus(VOStatus.NEW);
		initDefaultData((Performance) getMainVO(vo));

		Map<String, String> data = userJson != null && userJson.get("data") != null
				? (Map<String, String>) userJson.get("data")
				: null;
		if (data != null && data.size() > 0) {
			String parentKey = data.get("parentKey");
			String parentPk = data.get("parentPk");
			getMainVO(vo).setAttributeValue(parentKey, parentPk);
		}

		BillCodeContext billCodeContext = getBillCodeContext("hrpplperformance");
		if (billCodeContext == null) {
			throw new BusinessException("当前编码规则不存在，请到【编码规则定义-全局】节点检查是否存在" + "hrpplperformance");
		}
		if (billCodeContext.isPrecode()) {
			String pk_group = InvocationInfoProxy.getInstance().getGroupId();
			String code = getBillcodeManage().getPreBillCode_RequiresNew("hrpplperformance", pk_group, pk_group);
			getMainVO(vo).setAttributeValue("billno", code);
		}

		return vo;
	}

	@Override
	public AggPerformance preAddAggPerformance(Map<String, Object> userJson) throws BusinessException {
		AggPerformance result = null;

		Performance mainvo = new Performance();
		// I
		initDefaultData(mainvo);
		AggPerformance aggvo = new AggPerformance();
		aggvo.setParent(mainvo);
		result = aggvo;
		return preAddAggPerformance(result, userJson);
	}

	@Override
	public AggPerformance preEditAggPerformance(String pk) throws BusinessException {
		return dao.findByPk(AggPerformance.class, pk, false);
	}

	@Override
	public AggPerformance copyAggPerformance(String pk) throws BusinessException {

		AggPerformance vo = dao.findByPk(AggPerformance.class, pk, false);

		getMainVO(vo).setPrimaryKey(null);
		getMainVO(vo).setStatus(VOStatus.NEW);

		getMainVO(vo).setAttributeValue("srcbilltype", null);
		getMainVO(vo).setAttributeValue("srcbillid", null);

		getMainVO(vo).setAttributeValue("billno", null);
		getMainVO(vo).setAttributeValue("", null);
		BillCodeContext billCodeContext = getBillCodeContext("hrpplperformance");
		if (billCodeContext == null) {
			throw new BusinessException("-" + "hrpplperformance");
		}
		if (billCodeContext.isPrecode()) {
			String pk_group = InvocationInfoProxy.getInstance().getGroupId();
			String code = getBillcodeManage().getPreBillCode_RequiresNew("hrpplperformance", pk_group, pk_group);
			getMainVO(vo).setAttributeValue("billno", code);
		}
		getMainVO(vo).setAttributeValue("approvestatus", BillStatusEnum.FREE.toIntValue());
		getMainVO(vo).setAttributeValue("billmaker", InvocationInfoProxy.getInstance().getUserId());
		getMainVO(vo).setAttributeValue("approver", null);
		getMainVO(vo).setAttributeValue("approvenote", null);
		getMainVO(vo).setAttributeValue("approvedate", null);
		getMainVO(vo).setAttributeValue("creator", null);
		getMainVO(vo).setAttributeValue("creationtime", null);
		getMainVO(vo).setAttributeValue("modifier", null);
		getMainVO(vo).setAttributeValue("modifiedtime", null);
		getMainVO(vo).setAttributeValue("maketime", new UFDateTime(InvocationInfoProxy.getInstance().getBizDateTime()));

		Perapplybody[] perapplybodys = (Perapplybody[]) vo.getChildren(Perapplybody.class);
		if (perapplybodys != null && perapplybodys.length > 0) {
			Arrays.stream(perapplybodys).forEach(subvo -> {
				subvo.setPrimaryKey(null);
				subvo.setStatus(VOStatus.NEW);
				subvo.setAttributeValue("srcbilltype", null);
				subvo.setAttributeValue("srcbillid", null);
				subvo.setAttributeValue("rowno", null);
				subvo.setAttributeValue("srcrowno", null);
			});
		}
		Properbody[] properbodys = (Properbody[]) vo.getChildren(Properbody.class);
		if (properbodys != null && properbodys.length > 0) {
			Arrays.stream(properbodys).forEach(subvo -> {
				subvo.setPrimaryKey(null);
				subvo.setStatus(VOStatus.NEW);
				subvo.setAttributeValue("srcbilltype", null);
				subvo.setAttributeValue("srcbillid", null);
				subvo.setAttributeValue("", null);
				subvo.setAttributeValue("", null);
			});
		}
		return vo;
	}

	@Override
	public AggPerformance[] saveAggPerformance(AggPerformance vo) throws BusinessException {
		String pk = getVOPrimaryKey(vo);
		setDefaultVal(vo);
		uniqueValidate(vo);
		totalAmount(vo);
		if (StringUtils.isEmpty(pk)) {
			validate(vo);
			//新增时设置项目申请pk
			vo.getParentVO().setPk_pjapplication(vo.getParentVO().getPk_project());
			return dao.insert(vo);
		} else {
			return dao.update(vo);
		}
	}

	private void validate(AggPerformance vo) throws BusinessException {
		Performance headVO = vo.getParentVO();
		String condition = "performance_type = '" + headVO.getPerformance_type() + "' and pk_project ='"
				+ headVO.getPk_project() + "'";
		AggPerformance[] listAggPerformanceByCondition = listAggPerformanceByCondition(condition);
		if (listAggPerformanceByCondition != null && listAggPerformanceByCondition.length > 0) {
			Performance parentVO = listAggPerformanceByCondition[0].getParentVO();
			throw new BusinessException("当前年度，此项目已存在" + parentVO.getBillno() + "绩效评价，不能重复添加！");
		}

	}

	/**
	 * 唯一性校验
	 * 【需求文档】
	 * 	北大人民预算及项目库产品详细需求V2.0.docx
	 * 【需求内容】
	 * ----
	 * 保存验证：
	 * 绩效类型+预算类型+主管科室+项目+考核年度唯一校验。
	 * 表体绩效评份占比改为合计必输=90%. （预算执行是10%）
	 * 绩效指标评分占比相同一级大类下合计值必需等于大类占比。
	 * ----
	 */
	private void uniqueValidate(AggPerformance... vos) throws BusinessException {
		if(nccloud.commons.lang.ArrayUtils.isEmpty(vos)){
			return ;
		}

		for (AggPerformance vo : vos) {
			Performance parentVO = vo.getParentVO();
			// 删除不校验
			if(parentVO.getStatus() == VOStatus.DELETED) {
				continue;
			}
			// 表体合计校验
			Properbody[] children = (Properbody[])vo.getChildren(Properbody.class);
			if(ArrayUtils.isEmpty(children)) {
				continue;
			}
			// 大类合计
			Map<String, UFDouble> jxamistype1_total_map = new HashMap<>();

			UFDouble total = UFDouble.ZERO_DBL;
			for (Properbody child : children) {
				if(child.getStatus() == VOStatus.DELETED) {
					continue;
				}
				UFDouble score = child.getScore_proportion() == null ? UFDouble.ZERO_DBL : child.getScore_proportion();
				String jxamistype1 = child.getPk_jxamistype1();
				if(StringUtils.isNotBlank(jxamistype1)) {
					UFDouble type1Total = jxamistype1_total_map.get(jxamistype1);
					if(type1Total == null) {
						jxamistype1_total_map.put(jxamistype1,score);
					}else{
						jxamistype1_total_map.put(jxamistype1,type1Total.add(score));
					}
				}
				total = total.add(score);
			}
			if(total.doubleValue() != 90) {
				ExceptionUtils.wrappBusinessException("表体绩效评分占比合计必须等于90%.");
			}
			if(!jxamistype1_total_map.isEmpty()) {
				// 校验绩效指标评分占比相同一级大类下合计值必需等于大类占比
				// 查询 一级大类的占比
				IJXaimsTypeVOService jXaimsTypeVOService = NCLocator.getInstance().lookup(IJXaimsTypeVOService.class);
				JXaimsTypeVO[] jXaimsTypeVOS = jXaimsTypeVOService.listJXaimsTypeVOByPk(jxamistype1_total_map.keySet().toArray(new String[0]), true);
				if(ArrayUtils.isEmpty(jXaimsTypeVOS)) {
					ExceptionUtils.wrappBusinessException("未查询到一级大类，请检查。");
				}
				Map<String, JXaimsTypeVO> jXaimsTypeVOMap = new HashMap<>(jXaimsTypeVOS.length);
				for (JXaimsTypeVO jXaimsTypeVO : jXaimsTypeVOS) {
					jXaimsTypeVOMap.put(jXaimsTypeVO.getPk_jxaimstype(), jXaimsTypeVO);
				}

				for (Map.Entry<String, UFDouble> entry : jxamistype1_total_map.entrySet()) {
					JXaimsTypeVO typeVO = jXaimsTypeVOMap.get(entry.getKey());
					if(typeVO == null) {
						ExceptionUtils.wrappBusinessException("未查询到一级大类，请检查。");
					}
//					if(entry.getValue() == null || !entry.getValue().equals(typeVO.getNratio())) {
//						ExceptionUtils.wrappBusinessException("绩效指标评分占比相同一级大类下合计值必需等于大类占比");
//					}
				}

			}
			// 唯一性校验
			SqlBuilder whereSql = new SqlBuilder();
			whereSql.append(Performance.PERFORMANCE_TYPE,parentVO.getPerformance_type());
			whereSql.append(" and ");
			whereSql.append(Performance.PK_BUDGETTYPE,parentVO.getPk_budgettype());
			if(StringUtils.isNotBlank(parentVO.getPk_officedept())) {
				whereSql.append(" and ");
				whereSql.append(Performance.PK_OFFICEDEPT,parentVO.getPk_officedept());
			}
			whereSql.append(" and ");
			whereSql.append(Performance.PK_PROJECT,parentVO.getPk_project());
			whereSql.append(" and ");
			whereSql.append(Performance.ASSESS_YEAR,parentVO.getAssess_year());
			whereSql.append(" and dr = 0 ");
			if(nccloud.commons.lang.StringUtils.isNotBlank(parentVO.getPk_performance())) {
				whereSql.append(" and ");
				whereSql.appendNot(Performance.PK_PERFORMANCE,new String[]{parentVO.getPk_performance()});
			}
			AggPerformance[] existAggs = this.listAggPerformanceByCondition(whereSql.toString());
			if(existAggs != null && existAggs.length > 0) {
				ExceptionUtils.wrappBusinessException("【绩效类型+预算类型+主管科室+项目+考核年度】的单据已存在!");
			}

		}








	}

	/**
	 * 合计表体金额
	 * 【需求文档】
	 * 	北大人民预算及项目库产品详细需求V2.0.docx
	 * 	【需求内容】
	 * ----
	 * 年初预算数	数值	 取绩效信息页签“年初预算数”合计
	 * 全年预算数	数值	 取绩效信息页签“金额”合计
	 * 全年执行数	数值	 取绩效信息页签“执行金额”合计
	 * ----
	 * @param vos 参数
	 */
	private void totalAmount(AggPerformance... vos) throws BusinessException {
		if(ArrayUtils.isEmpty(vos)) {
			return ;
		}
		for (AggPerformance vo : vos) {
			Performance headVO = vo.getParentVO();
			Perapplybody[] bodys = (Perapplybody[])vo.getChildren(Perapplybody.class);
			if(ArrayUtils.isEmpty(bodys)) {
				continue ;
			}
			// 保存前先清空合计数据
			headVO.setYear_begin_budget(UFDouble.ZERO_DBL);
			headVO.setYear_all_budget(UFDouble.ZERO_DBL);
			headVO.setYear_all_exec(UFDouble.ZERO_DBL);

			for (Perapplybody body : bodys) {
				// 年初预算数	数值	 取绩效信息页签“年初预算数”合计
				headVO.setYear_begin_budget(headVO.getYear_begin_budget().add(getNotNull(body.getYear_begin_budget())));
				// 全年预算数	数值	 取绩效信息页签“金额”合计
				headVO.setYear_all_budget(headVO.getYear_all_budget().add(getNotNull(body.getAmount())));
				// 全年执行数	数值	 取绩效信息页签“执行金额”合计
				headVO.setYear_all_exec(headVO.getYear_all_exec().add(getNotNull(body.getExecution_amount())));
			}
			// 执行率=（全年执行数/全年预算数）* 100
			if(headVO.getYear_all_budget().doubleValue() > 0) {
				headVO.setImpl_rate(headVO.getYear_all_exec().div(headVO.getYear_all_budget()).multiply(100));
			} else {
				headVO.setImpl_rate(UFDouble.ZERO_DBL);
			}
			// 计算得分(分值*执行率)
			headVO.setFianl_score(getNotNull(headVO.getGrade()).multiply(headVO.getImpl_rate()));

		}
	}

	private void setBillCode(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isNotEmpty(vos)) {
			for (AggPerformance vo : vos) {
				String pk = getVOPrimaryKey(vo);
				if (StringUtils.isEmpty(pk)) {
					BillCodeContext billCodeContext = getBillCodeContext("hrpplperformance");
					String pk_group = InvocationInfoProxy.getInstance().getGroupId();
					if (billCodeContext != null && !billCodeContext.isPrecode()) {
						if (getMainVO(vo).getAttributeValue("billno") == null) {
							String code = getBillcodeManage().getBillCode_RequiresNew("hrpplperformance", pk_group,
									pk_group, getMainVO(vo));
							getMainVO(vo).setAttributeValue("billno", code);
						}
					} else {
						String code = (String) getMainVO(vo).getAttributeValue("billno");
						getBillcodeManage().commitPreBillCode("hrpplperformance", pk_group, pk_group, code);
					}
				}
			}
		}
	}

	private void setAuditInfo(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isNotEmpty(vos)) {
			UFDateTime now = new UFDateTime();
			for (AggPerformance vo : vos) {
				String pk = getVOPrimaryKey(vo);
				if (StringUtils.isEmpty(pk)) {
					getMainVO(vo).setAttributeValue("creator", InvocationInfoProxy.getInstance().getUserId());
					getMainVO(vo).setAttributeValue("creationtime", now);
					getMainVO(vo).setAttributeValue("maketime", now);
					getMainVO(vo).setAttributeValue("billmaker", InvocationInfoProxy.getInstance().getUserId()); //
					getMainVO(vo).setAttributeValue("modifier", null);
					getMainVO(vo).setAttributeValue("modifiedtime", null);
				} else {
					getMainVO(vo).setAttributeValue("modifier", InvocationInfoProxy.getInstance().getUserId());
					getMainVO(vo).setAttributeValue("modifiedtime", now);
					getMainVO(vo).setAttributeValue("lastmaketime", now);
				}
			}
		}
	}

	private void setDefaultVal(AggPerformance... vos) throws BusinessException {
		setBillCode(vos);
		setAuditInfo(vos);
	}

	@Override
	public AggPerformance[] saveAggPerformance(AggPerformance[] vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return new AggPerformance[0];
		}
		setDefaultVal(vos); //
		uniqueValidate(vos);
		List<String> pks = Arrays.stream(vos).filter(v -> getMainVO(v).getStatus() == VOStatus.DELETED)
				.map(v -> getMainVO(v).getPrimaryKey()).collect(Collectors.toList());
		if (pks == null || pks.size() == 0) {
			return dao.save(vos, true);
		}
		AggPerformance[] deleteVOs = dao.listByPk(AggPerformance.class, pks.toArray(new String[0]));
		for (int i = 0; i < deleteVOs.length; i++) {
			SuperVO mainVO = getMainVO(deleteVOs[i]);
			Integer approveStatus = (Integer) mainVO.getAttributeValue("approvestatus");
			if (approveStatus != null && !approveStatus.equals(-1)) {
				throw new BusinessException("第" + (i + 1) + "张单据处理失败：单据状态不正确，不能删除！");
			}
			String code = (String) mainVO.getAttributeValue("billno");
			if (StringUtils.isNotEmpty(code)) {
				String pk_group = InvocationInfoProxy.getInstance().getGroupId();
				getBillcodeManage().returnBillCodeOnDelete("hrpplperformance", pk_group, pk_group, code, deleteVOs[i]);
			}
		}
		return dao.save(vos, true);
	}

	@Override
	public AggPerformance[] deleteAggPerformances(Map<String, String> tsMap) throws BusinessException {
		AggPerformance[] vos = dao.listByPk(AggPerformance.class, tsMap.keySet().toArray(new String[0]));
		validate(vos, tsMap);
		String pk_group = InvocationInfoProxy.getInstance().getGroupId();
		Arrays.stream(vos).forEach(vo -> {
			String code = (String) getMainVO(vo).getAttributeValue("billno");
			try {
				getBillcodeManage().returnBillCodeOnDelete("hrpplperformance", pk_group, pk_group, code, vo);
			} catch (BusinessException e) {
				ExceptionUtils.wrappBusinessException(e.getMessage(), e);
			}
		});
		dao.delete(vos, true);
		return vos;
	}

	@Override
	public AggPerformance[] evaluateAggPerformances(Map<String, String> tsMap, String operete)
			throws BusinessException {
		AggPerformance[] vos = dao.listByPk(AggPerformance.class, tsMap.keySet().toArray(new String[0]));
		String pk_group = InvocationInfoProxy.getInstance().getGroupId();
		if ("effect".equals(operete)) {
			// 多条数据同时评价生效，需要将未绩效评价的数据删除掉
			validateBeforEva(vos);
			Arrays.stream(vos).forEach(vo -> ((Performance) vo.getParent()).setIsevaluation(new UFBoolean(true)));
		} else {
			Arrays.stream(vos).forEach(vo -> ((Performance) vo.getParent()).setIsevaluation(new UFBoolean(false)));
		}
		dao.update(vos);
		return vos;
	}

	private void validateBeforEva(AggPerformance[] vos) throws BusinessException {

		String error = "";
		if (ArrayUtils.isEmpty(vos)) {
			return;
		}
		for (int i = 0; i < vos.length; i++) {
			SuperVO mainvo = vos[i].getParentVO();
			ISuperVO[] children = vos[i].getChildren(Properbody.class);
			UFDouble performance_score = (UFDouble) children[0].getAttributeValue("performance_score");
			if (performance_score == null || UFDoubleUtils.isNullOrZero(performance_score)) {
				error += "第" + (i + 1) + "张单据处理失败：失败原因：单据未绩效评价，不允许评价生效！\n";
			}
		}
		if (!"".equals(error)) {
			throw new BusinessException(error);
		}
	}

	private void validate(AggPerformance[] vos, Map<String, String> tsMap) throws BusinessException {

		Boolean isPass = true;
		String error = "";
		if (ArrayUtils.isEmpty(vos)) {
			isPass = false;
		}

		for (int i = 0; i < vos.length; i++) {
			SuperVO mainvo = vos[i].getParentVO();
			UFDateTime ts = (UFDateTime) mainvo.getAttributeValue("ts");
			if (!StringUtils.equals(tsMap.get(mainvo.getPrimaryKey()), ts.toString())) {
				isPass = false;
				break;
			}
			Integer approvestatus = (Integer) mainvo.getAttributeValue("approvestatus");
			if (approvestatus == null || approvestatus != BillStatusEnum.FREE.toIntValue()) {
				error += "第" + (i + 1) + "张单据处理失败：审批状态不正确，不能删除！\n";
			}
		}
		if (!isPass) {
			throw new BusinessException("您操作的数据已被他人修改或删除，请刷新后重试！");
		}
		if (!"".equals(error)) {
			throw new BusinessException(error);
		}
	}

	@Override
	public <T> T[] loadTreeData(Class<T> clazz, Map<String, Object> userJson) throws BusinessException {
		String condition = "dr = 0 ";
		return dao.listByCondition(clazz, condition, false);
	}

	@Override
	public String[] queryChildPksByParentId(Class childClazz, String parentId) throws BusinessException {
		String cond = " pk_performance = '" + parentId + "' ";
		SuperVO[] vos = (SuperVO[]) dao.listByCondition(childClazz, cond, false);
		if (vos == null || vos.length == 0) {
			return new String[0];
		}
		return Stream.of(vos).map(vo -> vo.getPrimaryKey()).toArray(String[]::new);
	}

	public SuperVO[] queryChildVOByPks(Class childClazz, String[] pks) throws BusinessException {
		return (SuperVO[]) dao.listByPk(childClazz, pks, false);
	}

	/**
	 * 提交前校验: 检查单据状态
	 *
	 * @throws BusinessException
	 */
	private void validateCommitAggPerformance(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return;
		}
		List<AggPerformance> list = Arrays.stream(vos).filter(item -> item.getParentVO() != null).filter(item -> {
			Integer status = (Integer) item.getParentVO().getAttributeValue("approvestatus");
			return status == null
					|| status != BillStatusEnum.FREE.toIntValue() && status != BillStatusEnum.NOPASS.toIntValue();
		}).map(item -> item).collect(Collectors.toList());
		if (list == null || list.size() == 0) {
			return;
		}
		String errors = "";
		for (AggPerformance vo : list) {
			errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]提交失败，失败原因：单据状态不正确，请检查。\n";
		}
		throw new BusinessException(errors);
	}

	/**
	 * 收回前校验: 检查单据状态
	 *
	 * @throws BusinessException
	 */
	private void validateUnCommitAggPerformance(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return;
		}
		List<AggPerformance> list = Arrays.stream(vos).filter(item -> item.getParentVO() != null).filter(item -> {
			Integer status = (Integer) item.getParentVO().getAttributeValue("approvestatus");
			return status == null || status == BillStatusEnum.FREE.toIntValue();
		}).map(item -> item).collect(Collectors.toList());
		String errors = "";
		for (AggPerformance vo : list) {
			errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]收回失败，失败原因：单据状态不正确，请检查。\n";
		}
		List<AggPerformance> evaluationList = Arrays.stream(vos).filter(item -> item.getParentVO() != null)
				.filter(item -> {
					UFBoolean isevaluation = (UFBoolean) item.getParentVO().getAttributeValue("isevaluation");
					return isevaluation.booleanValue();
				}).map(item -> item).collect(Collectors.toList());
		if (evaluationList == null || evaluationList.size() == 0) {
			return;
		}
		for (AggPerformance vo : evaluationList) {
			errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]收回失败，失败原因：单据已评价，不允许收回。\n";
		}
		throw new BusinessException(errors);
	}

	@Override
	public Object commitAggPerformance(String actionName, Map<String, String> tsMap, Object assign)
			throws BusinessException {
		AggPerformance[] vos = dao.listByPk(AggPerformance.class, getAllPks(tsMap), false);
		validateTs(tsMap, vos);
		validateCommitAggPerformance(vos);
		Map<String, Object> res = this.execFlows(actionName, "JXPJ", assign, vos);
		return res;
	}

	@Override
	public Object batchCommitAggPerformance(String actionName, Map<String, String> tsMap) throws BusinessException {
		AggPerformance[] vos = dao.listByPk(AggPerformance.class, getAllPks(tsMap), false);
		validateTs(tsMap, vos);
		validateCommitAggPerformance(vos);
		Map<String, Object> res = this.execFlows(actionName, "JXPJ", vos);
		return res;
	}

	@Override
	public Object uncommitAggPerformance(String actionName, Map<String, String> tsMap) throws BusinessException {
		AggPerformance[] vos = dao.listByPk(AggPerformance.class, getAllPks(tsMap), false);
		validateTs(tsMap, vos);
		validateUnCommitAggPerformance(vos);
		Map<String, Object> res = this.execFlows(actionName, "JXPJ", vos);
		return res;
	}

	@Override
	public Object batchUncommitAggPerformance(String actionName, Map<String, String> tsMap) throws BusinessException {
		AggPerformance[] vos = dao.listByPk(AggPerformance.class, getAllPks(tsMap), false);
		validateTs(tsMap, vos);
		validateUnCommitAggPerformance(vos);
		Map<String, Object> res = this.execFlows(actionName, "JXPJ", vos);
		return res;
	}

	@Override
	public AggPerformance[] callbackSAVEBASE(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return null;
		}
		return this.saveAggPerformance(vos);

	}

	@Override
	public AggPerformance[] callbackSAVE(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return null;
		}
		Arrays.stream(vos).forEach(v -> {
			v.getParent().setAttributeValue("approvestatus", BillStatusEnum.COMMIT.toIntValue());
		});
		return this.saveAggPerformance(vos);

	}

	@Override
	public AggPerformance[] callbackUNSAVE(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return null;
		}
		return this.saveAggPerformance(vos);

	}

	@Override
	public AggPerformance[] callbackAPPROVE(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return null;
		}
		return this.saveAggPerformance(vos);

	}

	@Override
	public AggPerformance[] callbackUNAPPROVE(AggPerformance... vos) throws BusinessException {
		if (ArrayUtils.isEmpty(vos)) {
			return null;
		}
		List<AggPerformance> evaluationList = Arrays.stream(vos).filter(item -> item.getParentVO() != null)
				.filter(item -> {
					UFBoolean isevaluation = (UFBoolean) item.getParentVO().getAttributeValue("isevaluation");
					return isevaluation.booleanValue();
				}).map(item -> item).collect(Collectors.toList());
		if (evaluationList == null || evaluationList.size() == 0) {
			return this.saveAggPerformance(vos);
		}
		String errors="";
		for (AggPerformance vo : evaluationList) {
			errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]收回失败，失败原因：单据已评价，不允许收回。\n";
		}
		throw new BusinessException(errors);

	}

	@Override
	public BillCodeContext getBillCodeContext(String coderuleid) throws BusinessException {
		return super.getBillCodeContext(coderuleid);
	}

	@Override
	public BillCodeContext getBillCodeContext(String coderuleid, String pkgroup, String pkorg)
			throws BusinessException {
		return super.getBillCodeContext(coderuleid, pkgroup, pkorg);
	}

	@Override
	public AggPerformance pullDataByEmptyForPerformance(AggPerformance paramAgg) throws BusinessException {
		/*
		 * --北大人民预算及项目库产品详细需求V2.0.docx
		 * 1.预算类型=项目预算/支出预算/采购预算/资金预算/收支预算/业务预算/时，“主管科室”必输，考核年度必输，默认当前年度，可修改。选择预算类型，主管科室，考核年度，项目后，依据考核年度+主管科室+预算类型+项目，查询预算绩效目标单及项目信息，把表头及表体数据带出来。切换预算类型，主管科室，考核年度，项目任何一个都清空数据，重新获取数据。
		 * 2.预算类型=专项资金/科研经费时，“主管科室”非必输，自动带出，考核年度必输，默认当前年度，可修改;选择预算类型，考核年度，项目后，依据预算类型+考核年度+项目，查询科研/专项预算编制单中预算绩效目标及项目信息，把表头及表体数据带出来。切换预算类型，考核年度，项目任何一个都清空数据，重新获取数据。绩效页签内容：预算类型=科研经费/专项资金，如项目立项任务书中预算编制期间是“分年编制”时取年度预算编制单，预算编制期间是“按项目周期”，周期预算编制单。 表头关联信息选择项目后取立项任务书
		 * 3.预算类型=“”时，保持出有数据带出逻辑，选项目带出表头及表体信息。
		 */
		// 预算类型不为空时返回空对象
		if(paramAgg == null || paramAgg.getParentVO() == null || StringUtils.isNotBlank(paramAgg.getParentVO().getPk_budgettype())) {
			return null;
		}
		Performance paramHeadVO = paramAgg.getParentVO();
		// 获取当前项目
		String pk_project = paramHeadVO.getPk_project();
		if(StringUtils.isBlank(pk_project)) {
			return null;
		}
		// 查询项目申请
		IPJApplHVOService pjApplHVOService = NCLocator.getInstance().lookup(IPJApplHVOService.class);
		AggPjapplVO aggPjapplVO = pjApplHVOService.findAggPjapplVOByPk(pk_project);
		if(aggPjapplVO == null || aggPjapplVO.getParentVO() == null) {
			return null;
		}
		// 处理表头数据
		handleHeadVO(paramHeadVO, aggPjapplVO.getParentVO());

		// 处理表体数据（资金来源页签、绩效信息页签）
		// 资金来源
		List<Perapplybody> perapplybodyList = new ArrayList<>();
		PjapplBVO[] pjapplBVOS = (PjapplBVO[])aggPjapplVO.getChildren(PjapplBVO.class);
		if(ArrayUtils.isNotEmpty(pjapplBVOS)) {
			for (PjapplBVO pjapplBVO : pjapplBVOS) {
				Perapplybody newPerapplybody = new Perapplybody();
				newPerapplybody.setStatus(VOStatus.NEW);
				newPerapplybody.setRowno(pjapplBVO.getRowno());
				newPerapplybody.setPk_amountsource(pjapplBVO.getCapitalsource());
				newPerapplybody.setAmount(pjapplBVO.getAmount());
				newPerapplybody.setExecution_amount(pjapplBVO.getAmount());
				if(pjapplBVO.getAmount() != null){
					newPerapplybody.setExecution_rate(pjapplBVO.getAmount().div(pjapplBVO.getAmount()));
				}
				perapplybodyList.add(newPerapplybody);
			}
		}
		paramAgg.setChildren(Perapplybody.class, perapplybodyList.toArray(new Perapplybody[0]));
		// 绩效信息
		List<Properbody> properbodyList = new ArrayList<>();
		IJXaimsVOService service = NCLocator.getInstance().lookup(IJXaimsVOService.class);
		PjapplCVO[] pjapplCVOS = (PjapplCVO[])aggPjapplVO.getChildren(PjapplCVO.class);
		if(ArrayUtils.isNotEmpty(pjapplCVOS)) {
			for (PjapplCVO pjapplCVO : pjapplCVOS) {
				Properbody newProperbody = new Properbody();
				newProperbody.setStatus(VOStatus.NEW);
				newProperbody.setRowno(pjapplCVO.getRowno());
				newProperbody.setPk_jxamistype1(pjapplCVO.getPk_jxaimstypev1());
				newProperbody.setPk_jxamistype2(pjapplCVO.getPk_jxaimstypev2());
				newProperbody.setPk_jxamis(pjapplCVO.getPk_jxaims());
				newProperbody.setOppvalue(pjapplCVO.getOppvalue());

				JXaimsVO jXaimsVO = service.findJXaimsVOByPk(pjapplCVO.getPk_jxaims(),false);
				if(jXaimsVO != null) {
					newProperbody.setScore_proportion(jXaimsVO.getScore_proportion());
					newProperbody.setEstimated_completion(jXaimsVO.getAnnual_value());
					newProperbody.setCompare(jXaimsVO.getVcomparemark());
					newProperbody.setPk_unit(jXaimsVO.getCunit());
				}
				properbodyList.add(newProperbody);
			}
		}
		paramAgg.setChildren(Properbody.class, properbodyList.toArray(new Properbody[0]));
		return paramAgg;
	}

	@Override
	public AggPerformance pullDataByBudgetForPerformance(AggPerformance paramAgg) throws BusinessException {
		/*
		 * --北大人民预算及项目库产品详细需求V2.0.docx
		 * 1.预算类型=项目预算/支出预算/采购预算/资金预算/收支预算/业务预算/时，“主管科室”必输，考核年度必输，默认当前年度，可修改。选择预算类型，主管科室，考核年度，项目后，依据考核年度+主管科室+预算类型+项目，查询预算绩效目标单及项目信息，把表头及表体数据带出来。切换预算类型，主管科室，考核年度，项目任何一个都清空数据，重新获取数据。
		 * 2.预算类型=专项资金/科研经费时，“主管科室”非必输，自动带出，考核年度必输，默认当前年度，可修改;选择预算类型，考核年度，项目后，依据预算类型+考核年度+项目，查询科研/专项预算编制单中预算绩效目标及项目信息，把表头及表体数据带出来。切换预算类型，考核年度，项目任何一个都清空数据，重新获取数据。绩效页签内容：预算类型=科研经费/专项资金，如项目立项任务书中预算编制期间是“分年编制”时取年度预算编制单，预算编制期间是“按项目周期”，周期预算编制单。 表头关联信息选择项目后取立项任务书
		 * 3.预算类型=“”时，保持出有数据带出逻辑，选项目带出表头及表体信息。
		 */
		if(paramAgg == null || paramAgg.getParentVO() == null || StringUtils.isBlank(paramAgg.getParentVO().getPk_budgettype())) {
			ExceptionUtils.wrappBusinessException("未获取到参数，请检查！");
		}
		Performance paramHeadVO = paramAgg.getParentVO();

		IBusictrlTypeVOService busictrlTypeVOService = NCLocator.getInstance().lookup(IBusictrlTypeVOService.class);
		BusictrlTypeVO busictrlTypeVO = busictrlTypeVOService.findBusictrlTypeVOByPk(paramHeadVO.getPk_budgettype(),false);
		if(busictrlTypeVO == null || StringUtils.isBlank(busictrlTypeVO.getInnercode())) {
			ExceptionUtils.wrappBusinessException("[预算类型]字段信息必输");
		}
		if(StringUtils.isBlank(paramHeadVO.getAssess_year())) {
			ExceptionUtils.wrappBusinessException("[考核年度]字段信息必输");
		}
		if(StringUtils.isBlank(paramHeadVO.getPk_officedept())) {
			ExceptionUtils.wrappBusinessException("[主管科室]字段信息必输");
		}
		if(StringUtils.isBlank(paramHeadVO.getPk_org())) {
			ExceptionUtils.wrappBusinessException("[业务单元]字段信息必输");
		}
		// 获取当前项目
		String pk_project = paramHeadVO.getPk_project();
		if(StringUtils.isBlank(pk_project)) {
			ExceptionUtils.wrappBusinessException("[项目]字段信息必输");
		}
		if(!busictrlTypeVO.getInnercode().startsWith("YS")) {
			return null;
		}

		// 处理表头数据--根据项目绩效目标单（文档中写的预算绩效目标单，2024年5月9日已在群内确认）
		SqlBuilder whereSql = new SqlBuilder();
		whereSql.append(" dr = 0 and ");
		whereSql.append("pk_project", pk_project);
		List<ProjectHeadVO> projectHeadVOList = (List<ProjectHeadVO>)this.getDao().retrieveByClause(ProjectHeadVO.class,whereSql.toString());
		AggPjapplVO pjapplVO = null;
		if(projectHeadVOList != null && !projectHeadVOList.isEmpty()) {
			ProjectHeadVO projectHeadVO = projectHeadVOList.get(0);
			paramHeadVO.setPjcode(projectHeadVO.getProject_code());
			paramHeadVO.setPjname(projectHeadVO.getProject_name());
			paramHeadVO.setPjusename(projectHeadVO.getProject_ot_name());
			paramHeadVO.setStartingdate(projectHeadVO.getPlan_start_date());
			paramHeadVO.setClosingdate(projectHeadVO.getPlan_finish_date());
			paramHeadVO.setPjstatus(projectHeadVO.getEnablestate());
			paramHeadVO.setHeaduser(projectHeadVO.getPk_dutier());
			//20250225 yuqsh 申请科室取负责人所在科室
			pjapplVO = dao.findByPk(AggPjapplVO.class, pk_project, false);
			if (pjapplVO != null){
				PJApplHVO pjApplHVO = pjapplVO.getParentVO();
				paramHeadVO.setApplyyear(pjApplHVO.getApplyyear());
				paramHeadVO.setExeoffece(pjApplHVO.getExeoffece());
				paramHeadVO.setPjtotalcost(pjApplHVO.getPjtotalcost());
				paramHeadVO.setPjcontents(pjApplHVO.getPjcontents());
			}
		}
		//20250225 yuqsh 未查询到项目绩效目标单时，不提示错误
		//ExceptionUtils.wrappBusinessException("未查询到对应的绩效目标单中的项目信息，请检查");

		// fix: HPCLOUD-35841 绩评价单表头的预期目标要把项目预期目标表头的项目预期目标值带过来
		SqlBuilder queryBudgetperformancegoalsSql = new SqlBuilder();
		queryBudgetperformancegoalsSql.append(" select hbg.goals ");
		queryBudgetperformancegoalsSql.append(" from hrpbm_budgetperformancegoals hbg ");
		queryBudgetperformancegoalsSql.append(" where hbg.dr = 0 and ");
		queryBudgetperformancegoalsSql.append("hbg.pk_budgettype", paramHeadVO.getPk_budgettype());
		queryBudgetperformancegoalsSql.append(" and ");
		queryBudgetperformancegoalsSql.append("hbg.nyear", paramHeadVO.getAssess_year());
		queryBudgetperformancegoalsSql.append(" and ");
		queryBudgetperformancegoalsSql.append("hbg.pk_budgetdept", paramHeadVO.getPk_officedept());
		queryBudgetperformancegoalsSql.append(" and ");
		queryBudgetperformancegoalsSql.append("hbg.pk_project", paramHeadVO.getPk_project());
		queryBudgetperformancegoalsSql.append(" and ");
		queryBudgetperformancegoalsSql.append("hbg.pk_org", paramHeadVO.getPk_org());
		List<Map<String,Object>> resultMapList = (List<Map<String,Object>>)this.getDao().executeQuery(queryBudgetperformancegoalsSql.toString(),  new MapListProcessor());
		if(CollectionUtils.isNotEmpty(resultMapList)) {
			Map<String, Object> objectMap = resultMapList.get(0);
			if(objectMap != null) {
				Object goals = objectMap.get("goals");
				if(goals != null) {
					paramHeadVO.setAnticipate(goals.toString());
				}
			}
		}

		// 处理表体数据--资金来源--根据业务控制信息总览
		String queryBusiCtrlDataSql = getBusiCtrlDataSql(paramHeadVO,true, true);
		List<BusiCtrlDataVO> busiCtrlDataVOSList = (List<BusiCtrlDataVO>)this.getDao().executeQuery(queryBusiCtrlDataSql, new BeanListProcessor(BusiCtrlDataVO.class));
		if(CollectionUtils.isNotEmpty(busiCtrlDataVOSList)) {
			// 根据业务控制规则数据处理实际执行数
			// 查询业务控制明细
			SqlBuilder detailWhereSql = new SqlBuilder();
			detailWhereSql.append("pk_busictrldata", busiCtrlDataVOSList.stream().map(BusiCtrlDataVO::getPk_busictrldata).distinct().toArray(String[]::new));
			detailWhereSql.append(" and ");
			detailWhereSql.append("dim1",paramHeadVO.getAssess_year());
			// 处理时间范围
			if(paramHeadVO.getBegin_month() != null && paramHeadVO.getEnd_month() != null) {
				detailWhereSql.append(" and ");
				String beginMonth = paramHeadVO.getBegin_month() < 10 ? "0"+paramHeadVO.getBegin_month() : ""+paramHeadVO.getBegin_month();
				String endMonth = paramHeadVO.getEnd_month() < 10 ? "0"+paramHeadVO.getEnd_month() : ""+paramHeadVO.getEnd_month();
				String beginData = paramHeadVO.getAssess_year()+"-"+beginMonth+"-01 00:00:00";
				String endData = paramHeadVO.getAssess_year()+"-"+endMonth+"-31 23:59:59";
				detailWhereSql.append("cdbilldate between '" + beginData +"' and '"+endData+"' ");
			}
			Map<String,UFDouble> sumRealExecAmountMap = new HashMap<>(busiCtrlDataVOSList.size());
			List<BusiCtrlDetailVO> busiCtrlDetailVOList = (List<BusiCtrlDetailVO>)this.getDao().retrieveByClause(BusiCtrlDetailVO.class,detailWhereSql.toString());
			if(CollectionUtils.isNotEmpty(busiCtrlDetailVOList)) {
				for (BusiCtrlDetailVO busiCtrlDetailVO : busiCtrlDetailVOList) {
					UFDouble existAmount = sumRealExecAmountMap.get(busiCtrlDetailVO.getPk_busictrldata());
					if(existAmount == null) {
						existAmount = UFDouble.ZERO_DBL;
					}
					existAmount = existAmount.add(busiCtrlDetailVO.getExecuteamount());
					sumRealExecAmountMap.put(busiCtrlDetailVO.getPk_busictrldata(),existAmount);
				}
			}
			// 执行汇总-- 预算科室+项目+资金来源
			Map<String, BusiCtrlDataVO> unionKeyMap = new HashMap<>();
			// 计算执行数
			for (BusiCtrlDataVO busiCtrlDataVO : busiCtrlDataVOSList) {
				UFDouble realExecAmount = sumRealExecAmountMap.get(busiCtrlDataVO.getPk_busictrldata());
				busiCtrlDataVO.setExecuteamount(getNotNull(busiCtrlDataVO.getExecuteamount()));
				if(paramHeadVO.getBegin_month() != null && paramHeadVO.getEnd_month() != null) {
					busiCtrlDataVO.setExecuteamount(UFDouble.ZERO_DBL);
				}
				busiCtrlDataVO.setInitexecuteamount(getNotNull(busiCtrlDataVO.getInitexecuteamount()));
				busiCtrlDataVO.setControlamount(getNotNull(busiCtrlDataVO.getControlamount()));
				if(busiCtrlDataVO.getAttributeValue("adjustamount") == null) {
					busiCtrlDataVO.setAttributeValue("adjustamount",UFDouble.ZERO_DBL);
				}
				// 如果存在区间内的实际执行数，执行数=实际执行数+期初执行数
				if(realExecAmount != null) {
					busiCtrlDataVO.setExecuteamount(realExecAmount.add(busiCtrlDataVO.getInitexecuteamount()));
				}
				// 预算科室+项目+资金来源
				String unionKey = busiCtrlDataVO.getDim2() + busiCtrlDataVO.getDim3() + busiCtrlDataVO.getDim5();
				BusiCtrlDataVO existVO = unionKeyMap.get(unionKey);
				if(existVO == null) {
					unionKeyMap.put(unionKey,busiCtrlDataVO);
				}else {
					existVO.setControlamount(existVO.getControlamount().add(busiCtrlDataVO.getControlamount()));
					existVO.setExecuteamount(existVO.getExecuteamount().add(busiCtrlDataVO.getExecuteamount()));
				}

			}
			List<Perapplybody> perapplybodyList = new ArrayList<>(unionKeyMap.size());
			int rowNum = 1;
			for (Map.Entry<String, BusiCtrlDataVO> busiCtrlDataVOEntry : unionKeyMap.entrySet()) {
				BusiCtrlDataVO busiCtrlDataVO =  busiCtrlDataVOEntry.getValue();
				Perapplybody newVO = new Perapplybody();
				newVO.setStatus(VOStatus.NEW);
				newVO.setRowno(String.valueOf(rowNum*10));
				newVO.setPk_amountsource(busiCtrlDataVO.getDim5());
				newVO.setAmount(busiCtrlDataVO.getControlamount());
				newVO.setExecution_amount(busiCtrlDataVO.getExecuteamount());
				// 年初预算数=控制数-调整数
				UFDouble adjustAmount = busiCtrlDataVO.getAttributeValue("adjustamount") == null ? UFDouble.ZERO_DBL : new UFDouble(busiCtrlDataVO.getAttributeValue("adjustamount").toString());
				newVO.setYear_begin_budget(busiCtrlDataVO.getControlamount().sub(adjustAmount));
				newVO.setExecution_rate(newVO.getExecution_amount().div(newVO.getAmount()));
				rowNum++;
				perapplybodyList.add(newVO);
			}
			paramAgg.setChildren(Perapplybody.class, perapplybodyList.toArray(new Perapplybody[0]));
		} else {
			paramAgg.setChildren(Perapplybody.class, new Perapplybody[0]);
		}
		// 处理表体数据--绩效信息--根据预算绩效目标
		String queryPerformanceSql = getBudgetPerformanceSql(paramHeadVO);
		List<Properbody> performanceInfoVOList = (List<Properbody>)this.getDao().executeQuery(queryPerformanceSql, new BeanListProcessor(Properbody.class));
		if(CollectionUtils.isNotEmpty(performanceInfoVOList)) {
			for (Properbody body : performanceInfoVOList) {
				body.setStatus(VOStatus.NEW);
			}
			paramAgg.setChildren(Properbody.class, performanceInfoVOList.toArray(new Properbody[0]));
		} else {
			//20250225 yuqsh 未查询到项目绩效目标单时，绩效信息取项目申请表体绩效信息
			if(pjapplVO == null){
				pjapplVO = dao.findByPk(AggPjapplVO.class, pk_project, false);
			}
			if(pjapplVO != null){
				CircularlyAccessibleValueObject[]dd = pjapplVO.getChildrenVO();
				PjapplCVO[] cvos = (PjapplCVO[])pjapplVO.getChildren(PjapplCVO.class);
				if(cvos != null && cvos.length > 0){
					Set<String> pkList = new HashSet<>();
					for (PjapplCVO cvo:cvos){
						String pkJxaims = cvo.getPk_jxaims();
						pkList.add(pkJxaims);
					}
					Map<String, JXaimsVO> jXaimsVOData = getJXaimsVOData(pkList);
					performanceInfoVOList = new ArrayList<>();
					Properbody properbody = null;
					for (PjapplCVO cvo:cvos){
						properbody = new Properbody();
						properbody.setRowno(cvo.getRowno());
						properbody.setPk_jxamistype1(cvo.getPk_jxaimstypev1());
						properbody.setPk_jxamistype2(cvo.getPk_jxaimstypev2());
						properbody.setPk_jxamis(cvo.getPk_jxaims());
						properbody.setOppvalue(cvo.getOppvalue());
						properbody.setScore_proportion(cvo.getDim88());
						if(jXaimsVOData != null && cvo.getPk_jxaims() != null && jXaimsVOData.containsKey(cvo.getPk_jxaims())){
							JXaimsVO jXaimsVO = jXaimsVOData.get(cvo.getPk_jxaims());
							properbody.setCompare(jXaimsVO.getVcomparemark());
							properbody.setPk_unit(jXaimsVO.getCunit());
						}
						performanceInfoVOList.add(properbody);
					}
					paramAgg.setChildren(Properbody.class, performanceInfoVOList.toArray(new Properbody[0]));
				}
			}else{
				paramAgg.setChildren(Properbody.class, new Properbody[0]);
			}
		}

		return paramAgg;
	}

	private Map<String, JXaimsVO> getJXaimsVOData(Set<String> pkList) throws BusinessException {
		if(pkList != null && pkList.size() > 0){
			Map<String, JXaimsVO> map = new HashMap<>();
			JXaimsVO[] jXaimsVOS = dao.listByPk(JXaimsVO.class, pkList.toArray(new String[0]), false);
			if(jXaimsVOS != null && jXaimsVOS.length > 0){
				for (JXaimsVO jXaimsVO:jXaimsVOS){
					map.put(jXaimsVO.getPk_jxaims(), jXaimsVO);
				}
			}
			return map;
		}
		return null;
	}

	/**
	 * 构造查询业务控制数据信息sql
	 */
	private String getBusiCtrlDataSql(Performance paramHeadVO, boolean includeYear, boolean includeDept) {
		SqlBuilder queryFundSourceSql = new SqlBuilder();
		queryFundSourceSql.append(" select hbda.* ");
		queryFundSourceSql.append(" from hrpbctp_busictrldata hbda ");
		queryFundSourceSql.append(" inner join hrpbctp_busictrl hb on hb.pk_busictrl = hbda.pk_busictrl ");
		queryFundSourceSql.append(" where hb.dr = 0 and hbda.dr = 0 and ");
		// 表头业务控制类型--预算类型
		queryFundSourceSql.append("hb.pk_topbusictrltype", paramHeadVO.getPk_budgettype());
		queryFundSourceSql.append(" and ");
		queryFundSourceSql.append("hb."+BusiCtrlDataVO.PK_ORG, paramHeadVO.getPk_org());
		// 项目
		queryFundSourceSql.append(" and ");
		queryFundSourceSql.append("hbda."+BusiCtrlDataVO.DIM3, paramHeadVO.getPk_project());
		// 预算科室--主管科室
		if(includeDept) {
			queryFundSourceSql.append(" and ");
			queryFundSourceSql.append("hbda."+BusiCtrlDataVO.DIM2, paramHeadVO.getPk_officedept());
		}
		// 年度--考核年度
		if(includeYear) {
			queryFundSourceSql.append(" and ");
			queryFundSourceSql.append("hbda."+BusiCtrlDataVO.DIM1, paramHeadVO.getAssess_year());

		}
		return queryFundSourceSql.toString();
	}

	/**
	 * 根据预算绩效目标单构造绩效信息查询sql
	 */
	private static String getBudgetPerformanceSql(Performance paramHeadVO) {
		SqlBuilder queryPerformanceSql = new SqlBuilder();
		queryPerformanceSql.append(" select hpgs.rowno,");
		queryPerformanceSql.append(" hpgs.pk_jxamistype1 as pk_jxamistype1,");
		queryPerformanceSql.append(" hpgs.pk_jxamistype2 as pk_jxamistype2,");
		queryPerformanceSql.append(" hpgs.pk_jxamis      as pk_jxamis,");
		queryPerformanceSql.append(" hpgs.oppvalue,hpgs.scoreproportion as score_proportion,");
		queryPerformanceSql.append(" hpgs.funcode as compare,");
		queryPerformanceSql.append(" hpgs.unit as pk_unit");
		queryPerformanceSql.append(" from hrpbm_performancegoalsslave hpgs ");
		queryPerformanceSql.append(" inner join hrpbm_budgetperformancegoals hbg on hbg.pk_performancegoals = hpgs.pk_performancegoals ");
		queryPerformanceSql.append(" where hbg.dr = 0 and hpgs.dr= 0 and ");
		queryPerformanceSql.append("hbg.pk_budgettype", paramHeadVO.getPk_budgettype());
		queryPerformanceSql.append(" and ");
		queryPerformanceSql.append("hbg.nyear", paramHeadVO.getAssess_year());
		queryPerformanceSql.append(" and ");
		queryPerformanceSql.append("hbg.pk_budgetdept", paramHeadVO.getPk_officedept());
		queryPerformanceSql.append(" and ");
		queryPerformanceSql.append("hbg.pk_project", paramHeadVO.getPk_project());
		queryPerformanceSql.append(" and ");
		queryPerformanceSql.append("hbg.pk_org", paramHeadVO.getPk_org());
		return queryPerformanceSql.toString();
	}

	@Override
	public AggPerformance pullDataByHrpomForPerformance(AggPerformance paramAgg) throws BusinessException {
		/*
		 * --北大人民预算及项目库产品详细需求V2.0.docx
		 * 1.预算类型=项目预算/支出预算/采购预算/资金预算/收支预算/业务预算/时，“主管科室”必输，考核年度必输，默认当前年度，可修改。选择预算类型，主管科室，考核年度，项目后，依据考核年度+主管科室+预算类型+项目，查询预算绩效目标单及项目信息，把表头及表体数据带出来。切换预算类型，主管科室，考核年度，项目任何一个都清空数据，重新获取数据。
		 * 2.预算类型=专项资金/科研经费时，“主管科室”非必输，自动带出，考核年度必输，默认当前年度，可修改;选择预算类型，考核年度，项目后，依据预算类型+考核年度+项目，查询科研/专项预算编制单中预算绩效目标及项目信息，把表头及表体数据带出来。切换预算类型，考核年度，项目任何一个都清空数据，重新获取数据。绩效页签内容：预算类型=科研经费/专项资金，如项目立项任务书中预算编制期间是“分年编制”时取年度预算编制单，预算编制期间是“按项目周期”，周期预算编制单。 表头关联信息选择项目后取立项任务书
		 * 3.预算类型=“”时，保持出有数据带出逻辑，选项目带出表头及表体信息。
		 */
		// 预算类型不为空时返回空对象
		if(paramAgg == null || paramAgg.getParentVO() == null || StringUtils.isBlank(paramAgg.getParentVO().getPk_budgettype())) {
			ExceptionUtils.wrappBusinessException("未获取到参数，请检查！");
		}
		Performance paramHeadVO = paramAgg.getParentVO();
		IBusictrlTypeVOService busictrlTypeVOService = NCLocator.getInstance().lookup(IBusictrlTypeVOService.class);
		BusictrlTypeVO busictrlTypeVO = busictrlTypeVOService.findBusictrlTypeVOByPk(paramHeadVO.getPk_budgettype(),false);
		if(busictrlTypeVO == null || StringUtils.isBlank(busictrlTypeVO.getInnercode())) {
			ExceptionUtils.wrappBusinessException("[预算类型]字段信息必输");
		}
		if(StringUtils.isBlank(paramHeadVO.getAssess_year())) {
			ExceptionUtils.wrappBusinessException("[考核年度]字段信息必输");
		}
		if(StringUtils.isBlank(paramHeadVO.getPk_org())) {
			ExceptionUtils.wrappBusinessException("[业务单元]字段信息必输");
		}
		// 获取当前项目
		String pk_project = paramHeadVO.getPk_project();
		if(StringUtils.isBlank(pk_project)) {
			ExceptionUtils.wrappBusinessException("[项目]字段信息必输");
		}
		if(!busictrlTypeVO.getInnercode().startsWith("KY") && !busictrlTypeVO.getInnercode().startsWith("ZX")) {
			return null;
		}
		// 处理科研专项
		// 取类型前两位，用于拼接交易类型
		String suffixCode = busictrlTypeVO.getInnercode().substring(0,2);
		// 科研专项编制单的交易类型
		String transTypeCode = "OM10-Cxx-BZ-"+suffixCode;
		// 查询立项任务书--带出表头数据
		IProSetupTaskVOService proSetupTaskVOService = NCLocator.getInstance().lookup(IProSetupTaskVOService.class);
		String whereSql = ProSetupTaskVO.ISLASTVERSION+" = 'Y' and " + " pk_project = '"+pk_project+"'";
		AggProSetupTaskVO[] aggProSetupTaskVOS = proSetupTaskVOService.listAggProSetupTaskVOByCondition(whereSql, new String[]{ProSetupTaskVO.VERSIONNO});
		if(aggProSetupTaskVOS == null || aggProSetupTaskVOS.length == 0 || aggProSetupTaskVOS[0].getParentVO() == null) {
			ExceptionUtils.wrappBusinessException("未查询到对应的立项任务书，请检查");
		}
		// 默认取第一条数据
		ProSetupTaskVO proSetupTaskVO = aggProSetupTaskVOS[0].getParentVO();
		paramHeadVO.setPjcode(proSetupTaskVO.getCode());
		paramHeadVO.setPjname(proSetupTaskVO.getName());
		paramHeadVO.setPjusename(proSetupTaskVO.getName());
		paramHeadVO.setStartingdate(proSetupTaskVO.getStartdate());
		paramHeadVO.setClosingdate(proSetupTaskVO.getEnddate());
		paramHeadVO.setPjstatus(proSetupTaskVO.getProstatus());
		paramHeadVO.setApplyyear(proSetupTaskVO.getSetupyear());
		paramHeadVO.setPjtotalcost(proSetupTaskVO.getTopicmoney());
		// 240530 根据  HPCLOUD-34545 和 HPCLOUD-35002  最终确定，回写主管科室  9:20与葛佳莹确认
		paramHeadVO.setPk_officedept(proSetupTaskVO.getPk_dept_main());
		paramHeadVO.setHeaduser(proSetupTaskVO.getPk_director());
		paramHeadVO.setExeoffece(proSetupTaskVO.getPk_dept_accept());
		// 预算编制期间[1：分年；2：按项目周期]
		Integer period = proSetupTaskVO.getBudgetperiod();


		// fix: HPCLOUD-35841 绩评价单表头的预期目标要把项目预期目标表头的项目预期目标值带过来
		// 绩评价单如果从医院预算取数，表头的预期目标要把项目预期目标表头的项目预期目标值带过来。如果是从专项取数，也要从预算编制单表头“绩效预期目标”取到绩评价单预期目标中。
		SqlBuilder queryBudgetingSql = new SqlBuilder();
		queryBudgetingSql.append(" select hb.pk_budgeting,hb.kpitarget ");
		queryBudgetingSql.append(" from hrpom_budgeting hb ");
		queryBudgetingSql.append(" where hb.dr = 0 and ");
		queryBudgetingSql.append("hb.pk_org",paramHeadVO.getPk_org());
		queryBudgetingSql.append(" and ");
		queryBudgetingSql.append("hb.transtype",transTypeCode);
		queryBudgetingSql.append(" and ");
		queryBudgetingSql.append("hb.pk_project",paramHeadVO.getPk_project());
		if(period == 1) {
			queryBudgetingSql.append(" and ");
			queryBudgetingSql.append("hb.enableyear",Integer.valueOf(paramHeadVO.getAssess_year()));
		}
		List<Map<String,Object>> resultMapList = (List<Map<String,Object>>)this.getDao().executeQuery(queryBudgetingSql.toString(),  new MapListProcessor());
		if(CollectionUtils.isNotEmpty(resultMapList)) {
			Map<String, Object> objectMap = resultMapList.get(resultMapList.size() - 1);
			if(objectMap != null) {
				Object kpitarget = objectMap.get("kpitarget");
				if(kpitarget != null) {
					paramHeadVO.setAnticipate(kpitarget.toString());
				}
			}
		}



		// 处理表体数据--绩效信息--根据编制单
		SqlBuilder performanceQuerySql = new SqlBuilder();
		performanceQuerySql.append(" select hkd.*, hkd.targetvalue as oppvalue , hkd.scoreweight as score_proportion from hrpom_kpidetail hkd ");
		performanceQuerySql.append(" inner join hrpom_budgeting hb on hb.pk_budgeting = hkd.pk_budgeting ");
		performanceQuerySql.append(" where hb.dr = 0 and hkd.dr = 0 and ");
		performanceQuerySql.append("hb.pk_org",paramHeadVO.getPk_org());
		performanceQuerySql.append(" and ");
		performanceQuerySql.append("hb.transtype",transTypeCode);
		performanceQuerySql.append(" and ");
		performanceQuerySql.append("hb.pk_project",paramHeadVO.getPk_project());
		if(period == 1) {
			performanceQuerySql.append(" and ");
			performanceQuerySql.append("hb.enableyear",Integer.valueOf(paramHeadVO.getAssess_year()));
		}
		// fix：HPCLOUD-36097 参照科研经费取数，表体绩效信息数据重复 （有未知来源的重复数据，默认按最后一条取数，最新数据）
		if(CollectionUtils.isNotEmpty(resultMapList)) {
			Map<String, Object> objectMap = resultMapList.get(resultMapList.size() - 1);
			if(objectMap != null) {
				Object pk_budgeting = objectMap.get("pk_budgeting");
				if(pk_budgeting != null) {
					performanceQuerySql.append(" and ");
					performanceQuerySql.append("hb.pk_budgeting",pk_budgeting.toString());
				}
			}
		}
		List<Properbody> performanceInfoVOList = (List<Properbody>)this.getDao().executeQuery(performanceQuerySql.toString(), new BeanListProcessor(Properbody.class));
		if(CollectionUtils.isNotEmpty(performanceInfoVOList)) {
			for (Properbody body : performanceInfoVOList) {
				body.setStatus(VOStatus.NEW);
			}
			paramAgg.setChildren(Properbody.class, performanceInfoVOList.toArray(new Properbody[0]));
		}else {
			paramAgg.setChildren(Properbody.class, new Properbody[0]);
		}

		// 处理表体数据--资金来源--根据业务控制信息总览
		String queryBusiCtrlDataSql = getBusiCtrlDataSql(paramHeadVO,period == 1,false);
		List<BusiCtrlDataVO> busiCtrlDataVOSList = (List<BusiCtrlDataVO>)this.getDao().executeQuery(queryBusiCtrlDataSql, new BeanListProcessor(BusiCtrlDataVO.class));
		if(CollectionUtils.isNotEmpty(busiCtrlDataVOSList)) {
			// 根据业务控制规则数据处理实际执行数
			// 查询业务控制明细
			SqlBuilder detailWhereSql = new SqlBuilder();
			detailWhereSql.append("pk_busictrldata", busiCtrlDataVOSList.stream().map(BusiCtrlDataVO::getPk_busictrldata).distinct().toArray(String[]::new));
			detailWhereSql.append(" and ");
			detailWhereSql.append("dim1",paramHeadVO.getAssess_year());
			// 处理时间范围
			if(paramHeadVO.getBegin_month() != null && paramHeadVO.getEnd_month() != null) {
				detailWhereSql.append(" and ");
				String beginMonth = paramHeadVO.getBegin_month() < 10 ? "0"+paramHeadVO.getBegin_month() : ""+paramHeadVO.getBegin_month();
				String endMonth = paramHeadVO.getEnd_month() < 10 ? "0"+paramHeadVO.getEnd_month() : ""+paramHeadVO.getEnd_month();
				String beginData = paramHeadVO.getAssess_year()+"-"+beginMonth+"-01 00:00:00";
				String endData = paramHeadVO.getAssess_year()+"-"+endMonth+"-31 23:59:59";
				detailWhereSql.append("cdbilldate between '" + beginData +"' and '"+endData+"' ");
			}
			Map<String,UFDouble> sumRealExecAmountMap = new HashMap<>(busiCtrlDataVOSList.size());
			List<BusiCtrlDetailVO> busiCtrlDetailVOList = (List<BusiCtrlDetailVO>)this.getDao().retrieveByClause(BusiCtrlDetailVO.class,detailWhereSql.toString());
			if(CollectionUtils.isNotEmpty(busiCtrlDetailVOList)) {
				for (BusiCtrlDetailVO busiCtrlDetailVO : busiCtrlDetailVOList) {
					UFDouble existAmount = sumRealExecAmountMap.get(busiCtrlDetailVO.getPk_busictrldata());
					if(existAmount == null) {
						existAmount = UFDouble.ZERO_DBL;
					}
					existAmount = existAmount.add(busiCtrlDetailVO.getExecuteamount());
					sumRealExecAmountMap.put(busiCtrlDetailVO.getPk_busictrldata(),existAmount);
				}
			}
			// 执行汇总-- 预算科室+项目+资金来源
			Map<String, BusiCtrlDataVO> unionKeyMap = new HashMap<>();
			// 计算执行数
			for (BusiCtrlDataVO busiCtrlDataVO : busiCtrlDataVOSList) {
				UFDouble realExecAmount = sumRealExecAmountMap.get(busiCtrlDataVO.getPk_busictrldata());
				busiCtrlDataVO.setInitexecuteamount(getNotNull(busiCtrlDataVO.getInitexecuteamount()));
				busiCtrlDataVO.setControlamount(getNotNull(busiCtrlDataVO.getControlamount()));
				if(busiCtrlDataVO.getAttributeValue("adjustamount") == null) {
					busiCtrlDataVO.setAttributeValue("adjustamount",UFDouble.ZERO_DBL);
				}
				// 执行数=实际执行数+期初执行数
				busiCtrlDataVO.setExecuteamount(getNotNull(realExecAmount).add(busiCtrlDataVO.getInitexecuteamount()));
				// 预算科室+项目+资金来源
				String unionKey = busiCtrlDataVO.getDim2() + busiCtrlDataVO.getDim3() + busiCtrlDataVO.getDim5();
				BusiCtrlDataVO existVO = unionKeyMap.get(unionKey);
				if(existVO == null) {
					unionKeyMap.put(unionKey,busiCtrlDataVO);
				}else {
					existVO.setControlamount(existVO.getControlamount().add(busiCtrlDataVO.getControlamount()));
					existVO.setExecuteamount(existVO.getExecuteamount().add(busiCtrlDataVO.getExecuteamount()));
				}

			}
			List<Perapplybody> perapplybodyList = new ArrayList<>(unionKeyMap.size());
			int rowNum = 1;
			for (Map.Entry<String, BusiCtrlDataVO> busiCtrlDataVOEntry : unionKeyMap.entrySet()) {
				BusiCtrlDataVO busiCtrlDataVO =  busiCtrlDataVOEntry.getValue();
				Perapplybody newVO = new Perapplybody();
				newVO.setStatus(VOStatus.NEW);
				newVO.setRowno(String.valueOf(rowNum*10));
				newVO.setPk_amountsource(busiCtrlDataVO.getDim5());
				newVO.setAmount(busiCtrlDataVO.getControlamount());
				newVO.setExecution_amount(busiCtrlDataVO.getExecuteamount());
				// 年初预算数=控制数-调整数
				UFDouble adjustAmount = busiCtrlDataVO.getAttributeValue("adjustamount") == null ? UFDouble.ZERO_DBL : new UFDouble(busiCtrlDataVO.getAttributeValue("adjustamount").toString());
				newVO.setYear_begin_budget(busiCtrlDataVO.getControlamount().sub(adjustAmount));
				newVO.setExecution_rate(newVO.getExecution_amount().div(newVO.getAmount()));
				rowNum++;
				perapplybodyList.add(newVO);
			}
			paramAgg.setChildren(Perapplybody.class, perapplybodyList.toArray(new Perapplybody[0]));
		} else {
			paramAgg.setChildren(Perapplybody.class, new Perapplybody[0]);
		}

		return paramAgg;
	}


	/**
	 * 根据项目申请单处理表头数据
	 * @param headVO 当前表头
	 * @param pjApplHVO 项目申请表头
	 */
	public void handleHeadVO(Performance headVO, PJApplHVO pjApplHVO) {
		if(headVO == null || pjApplHVO == null) {
			return ;
		}
		headVO.setPk_pjapplication(pjApplHVO.getPk_pjappl());
		headVO.setPjcode(pjApplHVO.getBillno());
		headVO.setPjname(pjApplHVO.getPjname());
		headVO.setPjusename(pjApplHVO.getPjusename());
		headVO.setStartingdate(pjApplHVO.getStartingdate());
		headVO.setClosingdate(pjApplHVO.getClosingdate());
		headVO.setPjstatus(pjApplHVO.getPjstatus());
		headVO.setApplyyear(pjApplHVO.getApplyyear());
		headVO.setPjtotalcost(pjApplHVO.getPjtotalcost());
		headVO.setPk_officedept(pjApplHVO.getOfficedept());
		headVO.setHeaduser(pjApplHVO.getHeaduser());
		headVO.setExeoffece(pjApplHVO.getExeoffece());
		headVO.setPjcontents(pjApplHVO.getPjcontents());
		headVO.setPjperforobj(pjApplHVO.getPjperforobj());
	}

	/**
	 * 获取非空数值
	 * @param param 入参
	 * @return 为空返回0
	 */
	public UFDouble getNotNull(UFDouble param) {
		if(param == null) {
			return UFDouble.ZERO_DBL;
		}
		return param;
	}

}
